home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / ToolManager / Source / Library / entry.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  10KB  |  372 lines

  1. /*
  2.  * entry.c  V3.1
  3.  *
  4.  * ToolManager dock entry image class
  5.  *
  6.  * Copyright (C) 1990-98 Stefan Becker
  7.  *
  8.  * This source code is for educational purposes only. You may study it
  9.  * and copy ideas or algorithms from it for your own projects. It is
  10.  * not allowed to use any of the source codes (in full or in parts)
  11.  * in other programs. Especially it is not allowed to create variants
  12.  * of ToolManager or ToolManager-like programs from this source code.
  13.  *
  14.  */
  15.  
  16. #include "toolmanager.h"
  17.  
  18. /* Entry class instance data */
  19. struct EntryClassData {
  20.  struct TMImageData *ecd_ImageObject;
  21.  const char         *ecd_Text;
  22.  struct TextFont    *ecd_Font;
  23.  UWORD               ecd_ImageX;
  24.  UWORD               ecd_ImageY;
  25.  UWORD               ecd_TextLength;
  26.  UWORD               ecd_TextWidth;
  27.  UWORD               ecd_TextX;
  28.  UWORD               ecd_TextY;
  29.  
  30. };
  31. #define TYPED_INST_DATA(cl, o) ((struct EntryClassData *) INST_DATA((cl), (o)))
  32. #define IMAGE(i)               ((struct Image *) (i))
  33.  
  34. /* Entry class method: OM_NEW */
  35. #define DEBUGFUNCTION EntryClassNew
  36. static ULONG EntryClassNew(Class *cl, Object *obj, struct opSet *ops)
  37. {
  38.  ENTRYCLASS_LOG((LOG1(Tags, "0x%08lx", ops->ops_AttrList),
  39.                  PrintTagList(ops->ops_AttrList)))
  40.  
  41.  /* Call SuperClass */
  42.  if (obj = (Object *) DoSuperMethodA(cl, obj, (Msg) ops)) {
  43.   struct EntryClassData *ecd    = TYPED_INST_DATA(cl, obj);
  44.   UWORD                  width  = 0;
  45.   UWORD                  height = 0;
  46.   BOOL                   error  = FALSE;
  47.  
  48.   /* Initialize instance data */
  49.   ecd->ecd_ImageObject = NULL;
  50.   ecd->ecd_Text        = NULL;
  51.  
  52.   /* Display image? */
  53.   {
  54.    Object *image;
  55.  
  56.    /* Image object specified? */
  57.    if (image = (Object *) GetTagData(TMA_Image, NULL, ops->ops_AttrList)) {
  58.  
  59.     ENTRYCLASS_LOG(LOG1(Image, "0x%08lx", image))
  60.  
  61.     /* Attach image object */
  62.     if ((ecd->ecd_ImageObject =
  63.          (struct TMImageData *) DoMethod(image, TMM_GetImage, obj,
  64.                            GetTagData(TMA_Screen, NULL, ops->ops_AttrList)))) {
  65.  
  66.      ENTRYCLASS_LOG(LOG1(ImageData, "0x%08lx", ecd->ecd_ImageObject))
  67.  
  68.      /* Get image dimensions (NOTE: Frame size is hardcoded into this!) */
  69.      width  = ecd->ecd_ImageObject->tmid_Width  + 4;
  70.      height = ecd->ecd_ImageObject->tmid_Height + 2;
  71.     } else
  72.  
  73.      /* Couldn't get image -> error */
  74.      error = TRUE;
  75.    }
  76.   }
  77.  
  78.   /* Display text? */
  79.   if (error == FALSE) {
  80.  
  81.    /* Text specified? */
  82.    if (ecd->ecd_Text = (const char *)
  83.                         GetTagData(TMA_String, NULL, ops->ops_AttrList)) {
  84.     struct RastPort tmprp;
  85.  
  86.     ENTRYCLASS_LOG(LOG2(Text, "'%s' (0x%08lx)", ecd->ecd_Text, ecd->ecd_Text))
  87.  
  88.     /* Yes, we need the font then */
  89.     ecd->ecd_Font = (struct TextFont *)
  90.                      GetTagData(TMA_Font, NULL, ops->ops_AttrList);
  91.  
  92.     ENTRYCLASS_LOG(LOG1(Font, "0x%08lx", ecd->ecd_Font))
  93.  
  94.     /* Initialize RastPort */
  95.     InitRastPort(&tmprp);
  96.     SetFont(&tmprp, ecd->ecd_Font);
  97.  
  98.     /* Calculate string length and text width */
  99.     ecd->ecd_TextLength = strlen(ecd->ecd_Text);
  100.     ecd->ecd_TextWidth  = TextLength(&tmprp, ecd->ecd_Text,
  101.                                      ecd->ecd_TextLength);
  102.  
  103.     /* Set text dimensions */
  104.     if (width < (ecd->ecd_TextWidth + INTERWIDTH))
  105.      width = ecd->ecd_TextWidth + INTERWIDTH;
  106.     height += ecd->ecd_Font->tf_YSize + INTERHEIGHT;
  107.    }
  108.   }
  109.  
  110.   /* Check image dimensions */
  111.   if ((error == FALSE) && ((width == 0) || (height == 0)))
  112.  
  113.    /* Not a valid image */
  114.    error = TRUE;
  115.  
  116.   else {
  117.  
  118.    ENTRYCLASS_LOG(LOG2(Dimensions, "Width %ld Height %ld", width, height))
  119.  
  120.    /* Set Image dimensions */
  121.    IMAGE(obj)->Width  = width;
  122.    IMAGE(obj)->Height = height;
  123.   }
  124.  
  125.   /* Everything OK? */
  126.   if (error) {
  127.  
  128.    /* No, dispose object */
  129.    CoerceMethod(cl, obj, OM_DISPOSE);
  130.  
  131.    /* Clear object pointer */
  132.    obj = NULL;
  133.   }
  134.  }
  135.  
  136.  ENTRYCLASS_LOG(LOG1(Result, "0x%08lx", obj))
  137.  
  138.  return((ULONG) obj);
  139. }
  140.  
  141. /* Entry class method: OM_DISPOSE */
  142. #undef  DEBUGFUNCTION
  143. #define DEBUGFUNCTION EntryClassDispose
  144. static ULONG EntryClassDispose(Class *cl, Object *obj, Msg msg)
  145. {
  146.  struct EntryClassData *ecd = TYPED_INST_DATA(cl, obj);
  147.  
  148.  ENTRYCLASS_LOG(LOG0(Disposing))
  149.  
  150.  /* Image object attached? Release it */
  151.  if (ecd->ecd_ImageObject)
  152.   DoMethod(ecd->ecd_ImageObject->tmid_MemberData.tmmd_Object, TMM_Detach,
  153.            ecd->ecd_ImageObject);
  154.  
  155.  /* Call SuperClass */
  156.  return(DoSuperMethodA(cl, obj, msg));
  157. }
  158.  
  159. /* Entry class method: OM_SET */
  160. #undef  DEBUGFUNCTION
  161. #define DEBUGFUNCTION EntryClassSet
  162. static ULONG EntryClassSet(Class *cl, Object *obj, struct opSet *ops)
  163. {
  164.  struct TagItem *tstate = ops->ops_AttrList;
  165.  struct TagItem *ti;
  166.  
  167.  ENTRYCLASS_LOG((LOG1(Tags, "0x%08lx", ops->ops_AttrList),
  168.                  PrintTagList(ops->ops_AttrList)))
  169.  
  170.  /* Scan tag list */
  171.  while (ti = NextTagItem(&tstate))
  172.  
  173.   /* Which attribute shall be set? */
  174.   switch (ti->ti_Tag) {
  175.    case IA_Width: {
  176.      struct EntryClassData *ecd = TYPED_INST_DATA(cl, obj);
  177.  
  178.      /* Center image */
  179.      if (ecd->ecd_ImageObject)
  180.       ecd->ecd_ImageX = (ti->ti_Data - ecd->ecd_ImageObject->tmid_Width) / 2;
  181.  
  182.      /* Center text */
  183.      ecd->ecd_TextX = (ti->ti_Data - ecd->ecd_TextWidth) / 2;
  184.     }
  185.     break;
  186.  
  187.    case IA_Height: {
  188.      struct EntryClassData *ecd = TYPED_INST_DATA(cl, obj);
  189.  
  190.      /* Calculate new Y position */
  191.      if (ecd->ecd_Text) {
  192.  
  193.       /* Center text */
  194.       ecd->ecd_TextY = ti->ti_Data - ecd->ecd_Font->tf_YSize +
  195.                         ecd->ecd_Font->tf_Baseline - INTERHEIGHT / 2;
  196.  
  197.       /* Center image */
  198.       if (ecd->ecd_ImageObject)
  199.        ecd->ecd_ImageY = (ti->ti_Data - ecd->ecd_ImageObject->tmid_Height
  200.                           - ecd->ecd_Font->tf_YSize - INTERHEIGHT) / 2;
  201.  
  202.      } else
  203.  
  204.       /* Center image */
  205.       ecd->ecd_ImageY = (ti->ti_Data - ecd->ecd_ImageObject->tmid_Height)
  206.                          / 2;
  207.     }
  208.     break;
  209.   }
  210.  
  211.  /* Call SuperClass */
  212.  return(DoSuperMethodA(cl, obj, (Msg) ops));
  213. }
  214.  
  215. /* Entry class method: IM_DRAW */
  216. #undef  DEBUGFUNCTION
  217. #define DEBUGFUNCTION EntryClassDraw
  218. static ULONG EntryClassDraw(Class *cl, Object *obj, struct impDraw *id)
  219. {
  220.  struct EntryClassData *ecd = TYPED_INST_DATA(cl, obj);
  221.  
  222.  ENTRYCLASS_LOG(LOG0(Drawing))
  223.  
  224.  ENTRYCLASS_LOG(LOG2(Coord, "X %ld Y %ld", id->imp_Offset.X, id->imp_Offset.Y))
  225.  
  226.  /* Image valid? */
  227.  if (ecd->ecd_ImageObject) {
  228.   BltBitMapRastPort(ecd->ecd_ImageObject->tmid_ImageData, 0, 0, id->imp_RPort,
  229.                     ecd->ecd_ImageX + id->imp_Offset.X,
  230.                     ecd->ecd_ImageY + id->imp_Offset.Y,
  231.                     ecd->ecd_ImageObject->tmid_Width,
  232.                     ecd->ecd_ImageObject->tmid_Height, (ABC | ABNC));
  233.  }
  234.  
  235.  /* Text valid? */
  236.  if (ecd->ecd_Text) {
  237.  
  238.   /* Initialize RastPort */
  239.   SetFont(id->imp_RPort, ecd->ecd_Font);
  240.   SetABPenDrMd(id->imp_RPort,
  241.                id->imp_State == IDS_NORMAL ?
  242.                 id->imp_DrInfo->dri_Pens[TEXTPEN] :
  243.                 id->imp_DrInfo->dri_Pens[FILLTEXTPEN],
  244.                0, JAM1);
  245.  
  246.   /* Draw text */
  247.   Move(id->imp_RPort, ecd->ecd_TextX + id->imp_Offset.X,
  248.                       ecd->ecd_TextY + id->imp_Offset.Y);
  249.   Text(id->imp_RPort, ecd->ecd_Text, ecd->ecd_TextLength);
  250.  }
  251.  
  252.  /* Return 1 to indicate that the method is implemented */
  253.  return(1);
  254. }
  255.  
  256. /* Entry class method: TMM_Release */
  257. #undef  DEBUGFUNCTION
  258. #define DEBUGFUNCTION EntryClassRelease
  259. static ULONG EntryClassRelease(Class *cl, Object *obj, struct TMP_Detach *tmpd)
  260. {
  261.  struct EntryClassData *ecd = TYPED_INST_DATA(cl, obj);
  262.  
  263.  ENTRYCLASS_LOG(LOG2(Arguments, "Data 0x%08lx Object 0x%08lx",
  264.                      tmpd->tmpd_MemberData,
  265.                      tmpd->tmpd_MemberData->tmmd_Object))
  266.  
  267.  /* Image or Exec object released? */
  268.  if (tmpd->tmpd_MemberData) {
  269.  
  270.   /* Detach image object */
  271.   DoMethod(ecd->ecd_ImageObject->tmid_MemberData.tmmd_Object, TMM_Detach,
  272.            ecd->ecd_ImageObject);
  273.   ecd->ecd_ImageObject = NULL;
  274.  
  275.  } else
  276.  
  277.   /* Text has become invalid */
  278.   ecd->ecd_Text = NULL;
  279.  
  280.  /* Return 1 to indicate that the method is implemented */
  281.  return(1);
  282. }
  283.  
  284. /* Entry class method: TMM_Notify */
  285. #undef  DEBUGFUNCTION
  286. #define DEBUGFUNCTION EntryClassNotify
  287. static ULONG EntryClassNotify(Class *cl, Object *obj,
  288.                               struct TMP_Detach *tmpd)
  289. {
  290.  ENTRYCLASS_LOG(LOG2(Arguments, "Data 0x%08lx Member 0x%08lx",
  291.                      tmpd->tmpd_MemberData,
  292.                      tmpd->tmpd_MemberData->tmmd_Member))
  293.  
  294.  /* Detach image object */
  295.  DoMethod(tmpd->tmpd_MemberData->tmmd_Object, TMM_Detach,
  296.           tmpd->tmpd_MemberData);
  297.  
  298.  /* Clear image pointer */
  299.  TYPED_INST_DATA(cl, obj)->ecd_ImageObject = NULL;
  300.  
  301.  /* Return 1 to indicate that the method is implemented */
  302.  return(1);
  303. }
  304.  
  305. /* Entry class dispatcher */
  306. #undef  DEBUGFUNCTION
  307. #define DEBUGFUNCTION EntryClassDispatcher
  308. static __geta4 ULONG EntryClassDispatcher(__A0 Class *cl, __A2 Object *obj,
  309.                                           __A1 Msg msg)
  310. {
  311.  ULONG rc;
  312.  
  313.  ENTRYCLASS_LOG(LOG3(Arguments, "Class 0x%08lx Object 0x%08lx Msg 0x%08lx",
  314.                       cl, obj, msg))
  315.  
  316.  switch(msg->MethodID) {
  317.   /* BOOPSI methods */
  318.   case OM_NEW:
  319.    rc = EntryClassNew(cl, obj, (struct opSet *) msg);
  320.    break;
  321.  
  322.   case OM_DISPOSE:
  323.    rc = EntryClassDispose(cl, obj, msg);
  324.    break;
  325.  
  326.   case OM_SET:
  327.    rc = EntryClassSet(cl, obj, (struct opSet *) msg);
  328.    break;
  329.  
  330.   /* BOOPSI image methods */
  331.   case IM_DRAW:
  332.    rc = EntryClassDraw(cl, obj, (struct impDraw *) msg);
  333.    break;
  334.  
  335.   /* TM methods */
  336.   case TMM_Release:
  337.    rc = EntryClassRelease(cl, obj, (struct TMP_Detach *) msg);
  338.    break;
  339.  
  340.   case TMM_Notify:
  341.    rc = EntryClassNotify(cl, obj, (struct TMP_Detach *) msg);
  342.    break;
  343.  
  344.   /* Unknown method -> delegate to SuperClass */
  345.   default:
  346.    rc = DoSuperMethodA(cl, obj, msg);
  347.    break;
  348.  }
  349.  
  350.  return(rc);
  351. }
  352.  
  353. /* Create base class */
  354. #undef  DEBUGFUNCTION
  355. #define DEBUGFUNCTION CreateEntryClass
  356. const Class *CreateEntryClass(void)
  357. {
  358.  Class *cl;
  359.  
  360.  /* Create class */
  361.  if (cl = MakeClass(NULL, IMAGECLASS, NULL, sizeof(struct EntryClassData),
  362.                     0))
  363.  
  364.   /* Set dispatcher */
  365.   cl->cl_Dispatcher.h_Entry = (ULONG (*)()) EntryClassDispatcher;
  366.  
  367.  ENTRYCLASS_LOG(LOG1(Class, "0x%08lx", cl))
  368.  
  369.  /* Return pointer to class */
  370.  return(cl);
  371. }
  372.